import LeaderboardEntry = FBInstant.LeaderboardEntry;
import SharePayload = FBInstant.SharePayload;
import SignedPlayerInfo = FBInstant.SignedPlayerInfo;
import {userProfile} from "../../app/entity/UserProfile";
import Common from "../utils/Common";

export default class FacebookApi {

    public static isFbInstant() {
        // @ts-ignore
        return cc.sys.isObjectValid(window.FBInstant);
    }

    public static isFB() {
        // @ts-ignore
        return cc.sys.isObjectValid(window.FB);
    }

    public static share(title: string, imageUrl?: string, obj?: { from: string, extra?: any }): Promise<void> {
        if (!FacebookApi.isFbInstant()) {
            return Promise.reject("非FB 平台.");
        }
        const data = Common.assign({uid: userProfile.userId, player_id: FBInstant.player.getID()}, obj);
        const shareContent: SharePayload = {
            image: imageUrl,
            intent: "REQUEST",
            text: title,
            data,
        };
        return FBInstant.shareAsync(shareContent);
    }

    // 获取登录状态.
    public static getLoginStatus(): Promise<AuthResponse> {
        if (!FacebookApi.isFB()) {
            return Promise.resolve(null);
        }
        return new Promise<AuthResponse>((resolve) => {
            try {
                FB.getLoginStatus(((response) => {
                    if (response.status == "connected") {
                        resolve(response.authResponse);
                    } else {
                        resolve(null);
                    }
                }));
            } catch (e) {
                console.error("getLoginStatus", e);
            }
        });
    }

    public static async login(): Promise<SignedPlayerInfo> {
        return FBInstant.player.getSignedPlayerInfoAsync();
    }

    /**
     * 获取一个小排行榜数据,用于战败时展示.
     * @returns {Promise<FBInstant.LeaderboardEntry>}
     */
    public static async getMiniRankList(): Promise<LeaderboardEntry[]> {
        const count = await FacebookApi.getRankCount();
        const myRank = await FacebookApi.getMyRankEntry();
        if (!myRank) {
            return null;
        }
        let start = 0, size = count > 3 ? 3 : count;
        if (myRank.getRank() == 1) {
            start = 0;
        } else if (myRank.getRank() == count - 1) {
            start = count - 3;
        }
        if (start < 0) {
            start = 0;
        }
        cc.log("小排行起始位置:", start, size);
        return FacebookApi.getRankList(size, start, true);
    }

    /**
     * 获取玩家排行榜数据.
     * @param {number} count
     * @param {number} offset
     * @param {boolean} relative
     * @returns {Promise<FBInstant.LeaderboardEntry>}
     */
    public static getRankList(count: number = 50, offset: number = 0, relative: boolean = false): Promise<LeaderboardEntry[]> {
        if (!FacebookApi.isFbInstant()) {
            return Promise.reject("非FB 平台.");
        }
        return FBInstant.getLeaderboardAsync(this.RANK_NAME)
            .then((leaderboard) => {
                return leaderboard.getEntriesAsync(count, offset);
            });
    }

    /**
     * 获取排行榜总数.
     * @returns {Promise<number>}
     */
    public static getRankCount(): Promise<number> {
        if (!FacebookApi.isFbInstant()) {
            return Promise.reject("非FB 平台.");
        }
        return FBInstant.getLeaderboardAsync(this.RANK_NAME)
            .then((leaderboard) => {
                return leaderboard.getEntryCountAsync();
            });
    }

    /**
     * 获取玩家自己的排行榜数据.
     * @returns {Promise<FBInstant.LeaderboardEntry>}
     */
    public static getMyRankEntry(): Promise<LeaderboardEntry> {
        if (!FacebookApi.isFbInstant()) {
            return Promise.reject("非FB 平台.");
        }
        return FBInstant.getLeaderboardAsync(this.RANK_NAME)
            .then((leaderboard) => {
                return leaderboard.getPlayerEntryAsync();
            });
    }

    public static updateScore(score: number, level: number) {
        if (!FacebookApi.isFbInstant()) {
            return;
        }
        FBInstant.getLeaderboardAsync(this.RANK_NAME)
            .then((leaderboard) => {
                cc.log("获取排行榜:", leaderboard.getName());
                return leaderboard.setScoreAsync(score, JSON.stringify({ts: Date.now(), level}));
            }).then(() => {
            cc.log("Score saved");
        }).catch((error) => {
            // console.error("积分保存失败:" + JSON.stringify(error))
        });
    }

    public static getEntryPointAsync() {
        const entryPoint = FBInstant.getEntryPointAsync();
        cc.log("getEntryPointAsync:", entryPoint);
        const entryData = FBInstant.getEntryPointData();
        cc.log("entryData:", entryData);
    }

    /**
     * 创建快捷方式. 仅支持android 平台.
     */
    public static createShotcut() {
        cc.log("开始创建快捷方式");
        if (!FacebookApi.isFbInstant()) {
            return;
        }
        FBInstant.canCreateShortcutAsync()
            .then(function (canCreateShortcut) {
                cc.log("创建快捷方式开关:", canCreateShortcut);
                if (canCreateShortcut) {
                    FBInstant.createShortcutAsync()
                        .then(function () {
                            // Shortcut created
                            cc.log("创建快捷方式成功.");
                        })
                        .catch(function () {
                            // Shortcut not created
                            cc.log("创建快捷方式失败.");
                        });
                }
            });
    }

    /**
     * 匹配玩家.
     */
    public static matchOthers() {
        if (!FacebookApi.isFbInstant()) {
            return;
        }
        if (FBInstant.context.getID()) {
            cc.log("已经是通过群聊天启动游戏,无需重新匹配.");
            return;
        }
        FBInstant
            .checkCanPlayerMatchAsync()
            .then((canMatch) => {
                if (canMatch) {
                    FBInstant.matchPlayerAsync("level1", false).then(() => {
                        cc.log(FBInstant.context.getID());
                    }).catch(() => {
                    });
                }
            });
    }

    /**
     * 向某群发送正在游戏的推送消息. 要求自己也在这个群组中玩相同的游戏.
     * @param score
     * @param img
     */
    public static sendPlayMsgToGroup(score?: number, img?: string): boolean {
        if (!FacebookApi.isFbInstant()) {
            return false;
        }
        if (!FBInstant.context.getID()) {
            return false;
        }

        FBInstant.updateAsync({
            action: "CUSTOM",
            cta: "Join The Fight",
            image: img || null,
            text: `${FBInstant.player.getName()} Just got ${score || 1000} goals,Can you break it? `,
            template: "play_turn",
            strategy: "IMMEDIATE",
            notification: "NO_PUSH",
        }).then(function () {
            // closes the game after the update is posted.
            // FBInstant.quit();
            cc.log("发送失败.");
        });
        return true;
    }

    public static chooseOthers(): Promise<any> {
        return new Promise<any>((resolve, reject) => {
            FBInstant.context
                .chooseAsync()
                .then(function () {
                    cc.log(FBInstant.context.getID());
                    FacebookApi.sendPlayMsgToGroup();
                    resolve(FBInstant.context.getID());
                }).catch((reason) => {
                reject(reason);
            });
        });
    }

    private static readonly RANK_NAME: string = "GlobalRankList";
}
